package services;

import java.util.List;

import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;

import play.db.jpa.JPA;
import play.libs.Akka;
import play.libs.F;
import play.libs.F.Promise;
import play.libs.Json;
import play.libs.WS;
import play.libs.WS.Response;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;

public class NotificationsSrv extends UntypedActor {
	private static final String key = "key=AIzaSyCTxQYkcHDRNQNAGNPT7lam68no_wTMooI";
	private static final String gcmUrl = "https://android.googleapis.com/gcm/send";

	public static final ActorRef instance = Akka.system().actorOf(
			new Props(NotificationsSrv.class));

	@Override
	public void onReceive(final Object arg0) throws Exception {
		try {
			JPA.withTransaction(new F.Function0<String>() {

				@Override
				public String apply() throws Throwable {
					Notification notification = (Notification) arg0;
					Channel[] recipients = notification.getRecipients();
					Data data = notification.getData();

					ObjectNode obj = Json.newObject();
					ArrayNode jsonRgIds = obj.putArray("registration_ids");
					for (Channel recipient : recipients) {
						for (String id : recipient.androidIds()) {
							jsonRgIds.add(id);
						}
					}
					obj.put("data", Json.toJson(data));
					Promise<Response> fu = WS.url(gcmUrl)
							.setContentType("application/json")
							.setHeader("Authorization", key).post(obj);
					fu.map(new F.Function<Response, String>() {

						@Override
						public String apply(Response r) throws Throwable {
							System.out.println(r.getBody());
							return null;
						}
					});
					return null;
				}
			});
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void notify(Data data, Channel... recipients) {

		instance.tell(new Notification(recipients, data), instance);
	}

	public static class Notification {
		private Channel[] recipients;
		private Data data;

		public Notification(Channel[] recipients, Data data) {
			this.setRecipients(recipients);
			this.setData(data);
		}

		public Data getData() {
			return data;
		}

		public void setData(Data data) {
			this.data = data;
		}

		public Channel[] getRecipients() {
			return recipients;
		}

		public void setRecipients(Channel[] recipients) {
			this.recipients = recipients;
		}
	}

	public abstract static class Data {

	}

	public static class MensajeD extends Data {
		private Long id;
		private String preview;

		public MensajeD(Long id, String preview) {
			this.setId(id);
			this.setPreview(preview);
		}

		public Long getId() {
			return id;
		}

		public void setId(Long id) {
			this.id = id;
		}

		public String getPreview() {
			return preview;
		}

		public void setPreview(String preview) {
			this.preview = preview;
		}
	}

	public abstract static class Channel {
		public abstract List<String> androidIds();
	}

	public static class EstudianteR extends Channel {
		private Long id;

		public EstudianteR(Long id) {
			this.setId(id);
		}

		@Override
		public List<String> androidIds() {
			System.out.println("idEstudiante=" + id);
			return DAO
					.executeNative(
							"SELECT ni.notification_id FROM estudiante e "
									+ "JOIN acudiente a on a.id=e.id_acudiente "
									+ "JOIN notification_id ni on ni.id_persona=a.id_persona "
									+ "WHERE e.id=?idEstudiante", -1,
							"idEstudiante", id);
		}

		public Long getId() {
			return id;
		}

		public void setId(Long id) {
			this.id = id;
		}
	}

	public static class CursoR extends Channel {
		private Long id;

		public CursoR(Long id) {
			this.setId(id);
		}

		@Override
		public List<String> androidIds() {
			System.out.println("idCurso=" + id);
			return DAO.executeNative("SELECT ni.notification_id FROM curso c "
					+ "JOIN matricula m ON c.id=m.id_curso "
					+ "JOIN estudiante e ON e.id=m.id_estudiante "
					+ "JOIN acudiente a on a.id=e.id_acudiente "
					+ "JOIN notification_id ni ON ni.id_persona=a.id_persona "
					+ "WHERE c.id=?idCurso", -1, "idCurso", id);
		}

		public Long getId() {
			return id;
		}

		public void setId(Long id) {
			this.id = id;
		}
	}

	public static class GradoR extends Channel {

		private Long id;

		public GradoR(Long id) {
			this.setId(id);
		}

		@Override
		public List<String> androidIds() {
			// TODO Auto-generated method stub
			return null;
		}

		public Long getId() {
			return id;
		}

		public void setId(Long id) {
			this.id = id;
		}

	}

	public static class ColegioR extends Channel {

		private Long id;

		public ColegioR(Long id) {
			this.setId(id);
		}

		@Override
		public List<String> androidIds() {
			// TODO Auto-generated method stub
			return null;
		}

		public Long getId() {
			return id;
		}

		public void setId(Long id) {
			this.id = id;
		}

	}
}
